package com.acmedcare.framework.exchange.center.core.resolve;

import com.acmedcare.framework.kits.StringUtils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;

@Slf4j
public class HttpPathResolve implements IPathResolve {

  protected final String uri;

  protected String name;

  protected final String  rootPath;

  public HttpPathResolve(String uri, String rootPath) {
    this.uri = uri;
    this.rootPath = rootPath;
  }

  public HttpPathResolve(String uri, String name, String rootPath) {

    this.uri = uri;
    this.name = name;
    this.rootPath = rootPath;
  }

  @Override
  public String resolve() throws Exception {

    Path targetPath = getTargetPath();
    downloadFileToPath(uri, targetPath);
    return targetPath.toString();
  }

  public void downloadFileToPath(String url, Path target) {
    Instant now = Instant.now();
    try {

      if (Files.exists(target)) {

        Files.delete(target);
      }

      RestTemplate template = new RestTemplate();
      ClientHttpRequestFactory clientFactory = new HttpComponentsClientHttpRequestFactory();
      template.setRequestFactory(clientFactory);

      //定义请求头的接收类型
      RequestCallback requestCallback = request -> request.getHeaders()
          .setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
      // getForObject会将所有返回直接放到内存中,使用流来替代这个操作
      ResponseExtractor<Void> responseExtractor = response -> {
        // Here I write the response to a file but do what you like
        Files.copy(response.getBody(), target);
        return null;
      };

      template.execute(url, HttpMethod.GET, requestCallback, responseExtractor);
    } catch (Throwable e) {
      log.error("[下载文件] 写入失败:", e);
    }

    log.info("[下载文件] 完成,耗时:{}", ChronoUnit.MILLIS.between(now, Instant.now()));
  }


  protected Path getTargetPath() throws IOException {

    String fileName = uri.substring(uri.lastIndexOf(File.separator));
    if (StringUtils.isNotEmpty(name)) {
      fileName = name;
    }

    Path targetPath = Paths
        .get(rootPath + File.separator + fileName);

    //不存在文件夹时直接创建文件夹
    if (!Files.exists(Paths.get(rootPath))) {
      Files.createDirectories(Paths.get(rootPath));
    }

    return targetPath;
  }
}